using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
using System.Xml.Serialization;
using System.IO;
using Microsoft.SharePoint.Utilities;
using System.DirectoryServices;

namespace Community.SharePoint.Utilities.Branding
{
    #region SharePointHelper
    /// <summary>
    /// This class is developed to manage SharePoint Branding operations.
    /// Douglas Leung 2008-2009
    /// </summary>
    public class BrandingHelper
    {
        #region Constants
        public const string DEFAULT_LCID = "1033";
        public const string NONE_THEME = "none";
        #endregion

        #region Private Variables
        #endregion

        #region Public Variables
        public static string InstallationPath
        {
            get
            {
                return SPUtility.GetGenericSetupPath("");
            }
        }
        public static string LayoutsPath
        {
            get 
            {
                return SPUtility.GetGenericSetupPath(@"TEMPLATE\LAYOUTS\");
            }
        }
        public static string Lcid
        {
            get
            {
                string userDefault = BrandingHelper.GetSetting("UserLanguage");
                if (userDefault.Length > 0)
                {
                    return userDefault;
                }
                else
                {
                    return DEFAULT_LCID;
                }
            }
            set
            {
                BrandingHelper.SetSetting("UserLanguage", value);
            }
        }
        #endregion

        #region Public Methods
        #region GetSPWeb and GetSPSite
        private SPSite GetSPSite(string url)
        {
            SPSite _site;
            if (url.Length > 0 && url.ToLower().StartsWith("http:"))
            {
                _site = new SPSite(url);
            }
            else
            {
                _site = new SPSite("localhost");
            }
            return _site;
        }

        private SPWeb GetSPWeb(string url)
        {
            SPWeb returnweb;
            SPSite site;
            if (url.Length > 0 && url.ToLower().StartsWith("http:"))
            {
                site = new SPSite(url);
                returnweb = site.OpenWeb();
            }
            else
            {
                site = new SPSite("localhost");
                returnweb = site.OpenWeb();
            }
            return returnweb;
        }

        #endregion

        #region GetWebApplicationCollection
        /// <summary>
        /// Retrieves a list of web applications on the current server
        /// </summary>
        /// <returns>A SPWebApplicationCollection object that represts a list of SharePoint Web Applications.</returns>
        public static SPWebApplicationCollection GetWebApplicationCollection()
        {
            return SPWebService.ContentService.WebApplications;
        } 
        #endregion

        #region GetSPThemesXmlPath
        /// <summary>
        /// Returns the file path to the SPThemes Xml file (English - America) with LCID of 1033
        /// </summary>
        /// <returns>The path as a string</returns>
        public static string GetSPThemesXmlPath()
        {
            return GetSPThemesXmlPath(InstallationPath, Lcid);
        }

        /// <summary>
        /// Returns the file path to the SPThemes Xml file with a specified LCID
        /// </summary>
        /// <returns>The path as a string</returns>
        public static string GetSPThemesXmlPath(string sharepointPath, string lcid)
        {
            string _path = sharepointPath.EndsWith(@"\") ? sharepointPath : sharepointPath + @"\";
            string _lang = lcid;

            if (!IsValidPath())
            {
                throw new ArgumentException(string.Format("The SharePoint Path '{0}' could not be found. Is SharePoint installed properly?", LayoutsPath));
            }
            if (!IsValidLanguagePath(_path, _lang))
            {
                _lang = DEFAULT_LCID;
                if (!IsValidLanguagePath(_path, _lang))
                {
                    throw new ArgumentException(string.Format("The version of SharePoint that is installed is not the default (LCID: {0}). Please edit the configuration file attribute 'UserLanguage' to a valid path.", lcid));
                }
            }

            if (sharepointPath.EndsWith(@"\"))
            {
                return _path + @"TEMPLATE\LAYOUTS\" + _lang + @"\SPTHEMES.XML";
            }
            else
            {
                return _path + @"\TEMPLATE\LAYOUTS\" + _lang + @"\SPTHEMES.XML";
            }
        }
        #endregion

        #region GetWebTemplates
        /// <summary>
        /// Returns the web templates within the SharePoint Web Application with locale 1033
        /// </summary>
        /// <param name="webApplication">The SPWebApplication object</param>
        /// <returns></returns>
        public static SPWebTemplateCollection GetWebTemplates(SPWebApplication webApplication)
        {
            SPWebTemplateCollection siteTemplateCol = null;
            try
            {
                if (null != webApplication.Sites[0])
                {
                    siteTemplateCol = webApplication.Sites[0].GetWebTemplates(uint.Parse(Lcid));
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error getting Web Templates. \n\nCheck either:\n 1. LCID settings are correct\n 2. Web Application Templates or Site Definitions are installed with the correct LCID\n 3. SharePoint is installed.", ex);
            }
            return siteTemplateCol;
        }

        /// <summary>
        /// Returns the web templates within the SharePoint Web Application with specified lcid
        /// </summary>
        /// <param name="webApplication">The SPWebApplication object</param>
        /// <param name="lcid">The LCID</param>
        /// <returns></returns>
        public static SPWebTemplateCollection GetWebTemplates(SPWebApplication webApplication, string lcid)
        {
            SPWebTemplateCollection siteTemplateCol = null;
            if (null != webApplication.Sites[0])
            {
                siteTemplateCol = webApplication.Sites[0].GetWebTemplates(Convert.ToUInt32(lcid));
            }
            return siteTemplateCol;
        }

        #endregion

        #region IsValidPath
        /// <summary>
        /// Returns true if the path actually exists in the environment
        /// </summary>
        /// <returns></returns>
        public static bool IsValidPath()
        {
            return System.IO.Directory.Exists(InstallationPath + @"TEMPLATE\LAYOUTS\");
        }
        #endregion

        #region IsValidLanguagePath
        /// <summary>
        /// Returns true if the path actually exists in the environment
        /// </summary>
        /// <param name="path"></param>
        /// <param name="lcid"></param>
        /// <returns></returns>
        public static bool IsValidLanguagePath(string path, string lcid)
        {
            return System.IO.File.Exists(path + @"TEMPLATE\LAYOUTS\" + lcid + @"\SPTHEMES.XML");
        } 
        #endregion

        #region Application Settings
        #region ReloadSettings
        /// <summary>
        /// Loads saved settings from user.settings (C:\Documents and Settings\{current user}\Local Settings\Application Data\Douglas_Leung\SharePointBrandingTool.vs_Url_yad5xgfsubxbu24baoicwfzfolv1wc5j\1.7.5.0\)
        /// </summary>
        public static void ReloadSettings()
        {
            Properties.Settings.Default.Reload();
        }
        #endregion

        #region SaveSettings
        /// <summary>
        /// Saves settings to user.settings (C:\Documents and Settings\{current user}\Local Settings\Application Data\Douglas_Leung\SharePointBrandingTool.vs_Url_yad5xgfsubxbu24baoicwfzfolv1wc5j\1.7.5.0\)
        /// </summary>
        public static void SaveSettings()
        {
            Properties.Settings.Default.Upgrade();
            Properties.Settings.Default.Save();            
        }
        #endregion 
        #endregion

        #region GetSetting
        /// <summary>
        /// Retrieves a setting
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetSetting(string key)
        {
            string value = string.Empty;
            switch (key)
            {
                case "UserLanguage":
                    value = Properties.Settings.Default.UserLanguage;
                    break;
                default:
                    value = string.Empty;
                    break;
            }
            return value;
        } 
        #endregion

        #region SetSetting
        public static void SetSetting(string key, string value)
        {
            switch (key)
            {
                case "UserLanguage":
                    Properties.Settings.Default.UserLanguage = value;
                    break;
            }
            Properties.Settings.Default.Save();
        } 
        #endregion

        #region Logging

        public static string GetTempPath()
        {
            string path = System.Environment.CurrentDirectory;
            return path;
        }

        public static void WriteToLog(string msg)
        {
            System.IO.StreamWriter sw = System.IO.File.AppendText(
                GetTempPath() + String.Format("BrandingTool{0}-{1}-{2}.txt", DateTime.Now.Day.ToString(), DateTime.Now.Month.ToString(), DateTime.Now.Year.ToString()));
            try
            {
                string logLine = System.String.Format(
                    "{0:G}: {1}.", System.DateTime.Now, msg);
                sw.WriteLine(logLine);
            }
            finally
            {
                sw.Close();
            }
        }
        #endregion

        #region RecycleApplicationPool
        /// <summary>
        /// Recycles the target application pool
        /// </summary>
        /// <param name="appPoolId">The name of the application pool</param>
        public static void RecycleApplicationPool(string appPool)
        {
            string appPoolPath = "IIS://localhost/W3SVC/AppPools/" + appPool;

            DirectoryEntry appPoolEntry = new DirectoryEntry(appPoolPath);
            appPoolEntry.Invoke("Recycle");
        } 
        #endregion

        #region GetApplicationPools
        /// <summary>
        /// Returns a list of application pool names
        /// </summary>
        /// <returns></returns>
        public static List<SPApplicationPool> GetApplicationPools()
        {
            List<SPApplicationPool> result = new List<SPApplicationPool>();
            if (SPWebService.ContentService != null)
            {
                foreach (SPApplicationPool pool in SPWebService.ContentService.ApplicationPools)
                {
                    result.Add(pool);
                }
            }
            return result;
        } 
        #endregion
        #endregion

        #region Private Methods

        #endregion
    }
    #endregion

    #region LocalisationList
    /// <summary>
    /// This class was created to serialise a XML file storing all locale information
    /// </summary>
    [Serializable]
    [XmlRoot("localization")]
    public class LocalisationList
    {
        [XmlElement("locale")]
        public List<Localisation> items;

        public LocalisationList()
        {
            items = new List<Localisation>();
        }

        public void ToXml()
        {
            SerializeObject(this);
        }

        /// <summary>
        /// Loads all Locale definitions to class instance
        /// </summary>
        public void LoadFromXml()
        {
            items = new List<Localisation>();
            LocalisationList tempList = new LocalisationList();
            tempList = DeserializeObject("ListOfLCIDs.xml");
            this.items.Clear();
            foreach (Localisation l in tempList.items)
            {
                items.Add(l);
            }
        }

        /// <summary>
        /// Loads all Locale definitions that is available in the SharePoint Directory
        /// </summary>
        public void LoadAvailableLanguages()
        {
            LocalisationList tempList = new LocalisationList();
            tempList = DeserializeObject("ListOfLCIDs.xml");
            this.items.Clear();
            foreach (Localisation l in tempList.items)
            {
                if (BrandingHelper.IsValidLanguagePath(BrandingHelper.InstallationPath, l.Lcid))
                {
                    this.items.Add(l);
                }
            }
        }

        /// <summary>
        /// Method to serialise an object
        /// </summary>
        /// <param name="obj">Object that is to be serialized to XML</param>
        /// <returns>XML string</returns>
        public void SerializeObject(LocalisationList obj)
        {
            try
            {
                XmlSerializer s = new XmlSerializer(typeof(LocalisationList));
                TextWriter w = new StreamWriter("ListOfLCIDs.xml");
                s.Serialize(w, obj);
                w.Close();
            }
            catch
            {
            }
        } 

        /// <summary>
        /// Method to reconstruct an Object from XML string
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public LocalisationList DeserializeObject(string path)
        {
            LocalisationList obj;
            XmlSerializer s = new XmlSerializer(typeof(LocalisationList));
            TextReader r = new StreamReader(path);
            obj = (LocalisationList)s.Deserialize(r);
            r.Close();
            return obj;
        }

        /// <summary>
        /// Returns a list of LCID
        /// </summary>
        /// <returns>A list of Language names and their respective LCID codes</returns>
        public Dictionary<string, string> GetLCIDList()
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            foreach (Localisation l in this.items)
            {
                values.Add(l.Language, l.Lcid);
            }
            return values;
        }

        public Localisation GetLocalisation(string language)
        {
            foreach (Localisation l in items)
            {
                if (l.Language.Equals(language))
                {
                    return l;
                }
            }

            //return Default
            return new Localisation("English - United States", "1033");
        }

        public Localisation GetLocalisation(int lcid)
        {
            foreach (Localisation l in items)
            {
                if (l.Lcid.Equals(lcid.ToString()))
                {
                    return l;
                }
            }
            //return Default
            return new Localisation("English - United States", "1033");
        }
    }
    #endregion

    #region Localisation
    /// <summary>
    /// This class was created to serialise a XML file storing locale information
    /// More LCID codes at http://www.microsoft.com/globaldev/reference/lcid-all.mspx
    /// </summary>
   public class Localisation
    {
        private string m_language;
        [XmlElement("language")]
        public string Language
        {
            get { return m_language; }
            set { m_language = value; }
        }

        private string m_lcid;
        [XmlElement("lcid")]
        public string Lcid
        {
            get { return m_lcid; }
            set { m_lcid = value; }
        }

        public Localisation()
        { }

        public Localisation(string language)
        {
            Language = language;
        }

        public Localisation(string language, string lcid)
        {
            Language = language;
            Lcid = lcid;
        }
    }
    #endregion


}
